package com.java.wx.controller;

import com.java.bean.Message;
import com.java.bean.User;
import com.java.exception.DuplicateException;
import com.java.mvc.Body;
import com.java.mvc.View;
import com.java.service.CourierService;
import com.java.service.UserService;
import com.java.util.EmailUtil;
import com.java.util.JSONUtil;
import com.java.util.RandomUtil;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.security.GeneralSecurityException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Objects;

public class EmailController {

    // 生成随机码，发送邮件
    @Body("/email/sendEmail.do")
    public String sendEmail(HttpServletRequest req, HttpServletResponse resp) {
        final String email = req.getParameter("email");
        if (UserService.getUserByEmail(email) != null || CourierService.getCourierByEmail(email) != null) {
            return new Message(-2, "该邮箱地址已被注册").toJSON();
        }
        final HttpSession session = req.getSession();
        // 先从 session 中获取验证码， 即使用户重复发送邮件也不会有不同的验证码
        // 如果获取到为 null 则生成一个验证码存入 session 中
        String code = (String) session.getAttribute(email);
        if (code == null) {
            code = RandomUtil.genStr(6);
            session.setAttribute(email, code);
        }
        try {
            // 发送邮件
            if (EmailUtil.send(email, code)) {
                session.setAttribute("isAutoVerify", false);

                // 开启一个新的线程在 5 分钟后移除 session 中的数据
                Thread t = (Thread) session.getAttribute("t");
                if (t != null) {
                    t.interrupt();
                }
                t = new Thread(() -> {
                    try {
                        Thread.sleep(5 * 60 * 1000);
                        session.removeAttribute("t");
                        session.removeAttribute(email);
                        session.removeAttribute("isAutoVerify");
                        session.removeAttribute("verified");
                        session.removeAttribute("emailCode");
                    } catch (InterruptedException ignored) {}
                });
                t.start();
                session.setAttribute("t", t);
                return JSONUtil.toJSON(new Message(0, "邮件发送成功"));
            }
        } catch (GeneralSecurityException ignored) {}
        return JSONUtil.toJSON(new Message(-1, "邮件发送失败"));
    }

    // 登录页面监视邮件是否自动验证
    @Body("/email/bindAutoVerify.do")
    public String bindAutoVerify(HttpServletRequest req, HttpServletResponse resp) {
        final HttpSession session = req.getSession();
        final String email = req.getParameter("email");
        final Boolean isAutoVerify = (Boolean) session.getAttribute("isAutoVerify");
        if (isAutoVerify == null) {
            return new Message(1).toJSON();
        }
        if (isAutoVerify) {
            final String code = (String) session.getAttribute(email);
            return code == null ? JSONUtil.toJSON(new Message(-2, "邮箱地址与验证码不匹配")) : JSONUtil.toJSON(new Message(0, code));
        }
        return JSONUtil.toJSON(new Message(-1));
    }

    // 用户在注册页输入框输入验证码
    @Body("/log/reg.do")
    public String reg(HttpServletRequest req, HttpServletResponse resp) {
        final String name = req.getParameter("name");
        final String email = req.getParameter("email");
        final String password = req.getParameter("password");
        final String code = req.getParameter("code");
        String autoLogin = req.getParameter("autoLogin");
        final HttpSession session = req.getSession();
        session.setAttribute("isAutoVerify", false);
        if (code != null && code.equals(session.getAttribute(email))) {
            final User user = new User(name, null, password, new Timestamp(new Date().getTime()), email);
            int status;
            String message;
            try {
                status = UserService.insert(user);
                message = "注册成功";
                // 添加自动登录的 cookie
                Cookie cookie = new Cookie("autoLogin", "true".equals(autoLogin) ? email : "false");
                cookie.setMaxAge(7 * 24 * 60 * 60);
                cookie.setPath("/");
                resp.addCookie(cookie);
            } catch (DuplicateException e) {
                status = e.getType().getVal();
                switch (e.getType()) {
                    default:
                        message = "注册失败";
                        break;
                    case DUPLICATE_NAME:
                        message = "用户名已被占用";
                        break;
                    case DUPLICATE_PHONE:
                        message = "电话号码已被注册";
                        break;
                    case DUPLICATE_EMAIL:
                        message = "电子邮箱地址已被注册";
                        break;
                }
            }
            if (status >= 0) {
                session.setAttribute("user", user);
                session.removeAttribute("isAutoVerify");
            }
            return JSONUtil.toJSON(new Message(status, message));
        }
        return new Message(-6, "验证码错误").toJSON();
    }

    // 邮件自动进行验证
    @View("/email/autoVerify.do")
    public String autoVerify(HttpServletRequest req, HttpServletResponse resp) {
        final long time = Long.parseLong(req.getParameter("time"));
        if (new Date().getTime() - time > 5 * 60 * 1000) {
            // 验证码已超时失效
            return "/email/invalid.html";
        }
        final String email = req.getParameter("email");
        final String code = req.getParameter("code");
        final HttpSession session = req.getSession();
        final String sysCode = (String) session.getAttribute(email);
        if (code != null && code.equals(sysCode)) {
            session.setAttribute("isAutoVerify", true);
            session.setAttribute("emailCode", sysCode);
            return "/email/success.html";
        }
        if (code != null && sysCode == null) {
            session.setAttribute("verified", code);
            return "/email/verify.html";
        }
        return "/email/failed.html";
    }

    // 邮件端获取验证码
    @Body("/email/getCode.do")
    public String getCode(HttpServletRequest req, HttpServletResponse resp) {
        final HttpSession session = req.getSession();
        final String verified = (String) session.getAttribute("verified");
        if (verified != null) {
            // 邮件与注册页不是同一个session
            session.invalidate();
            return new Message(0, verified).toJSON();
        } else {
            // 邮件与注册页是同一个session
            return new Message(0, (String) session.getAttribute("emailCode")).toJSON();
        }
    }
}
